package org.example.domain.model.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.example.context.SecurityContextHolder;
import org.example.domain.model.entity.url.*;
import org.example.domain.model.entity.url.mapstruct.UrlShortenerAccessLogsMapstruct;
import org.example.domain.model.entity.url.req.UrlShortenerGroupStatsAccessRecordReq;
import org.example.domain.model.entity.url.req.UrlShortenerGroupStatsReq;
import org.example.domain.model.entity.url.req.UrlShortenerStatsAccessRecordReq;
import org.example.domain.model.entity.url.req.UrlShortenerStatsReq;
import org.example.domain.model.entity.url.resp.UrlShortenerStatsResp;
import org.example.domain.model.entity.url.vo.*;
import org.example.domain.repository.*;
import org.example.web.exception.ServerException;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
@RequiredArgsConstructor
public class UrlShortenerStatsDomainService {
    private final UrlShortenerRepository urlShortenerRepository;
    private final UrlShortenerCorrelationGroupMapperRepository urlShortenerCorrelationGroupMapperRepository;
    private final UrlShortenerAccessStatsRepository urlShortenerAccessStatsRepository;
    private final UrlShortenerLocaleStatsRepository urlShortenerLocaleStatsRepository;
    private final UrlShortenerOsStatsRepository urlShortenerOsStatsRepository;
    private final UrlShortenerBrowserStatsRepository urlShortenerBrowserStatsRepository;
    private final UrlShortenerDeviceStatsRepository urlShortenerDeviceStatsRepository;
    private final UrlShortenerNetworkStatsRepository urlShortenerNetworkStatsRepository;
    private final UrlShortenerAccessLogsRepository urlShortenerAccessLogsRepository;
    private final UrlShortenerStatsTodayRepository urlShortenerStatsTodayRepository;


    public UrlShortenerStatsResp oneUrlShortenerStats(UrlShortenerStatsReq urlShortenerStatsReq) {
        checkGroupBelongToUser(urlShortenerStatsReq.getGid());
        List<UrlShortenerAccessStats> urlShortenerAccessStatsList = urlShortenerAccessStatsRepository.listStatsByUrlShortener(urlShortenerStatsReq);
        if (CollUtil.isEmpty(urlShortenerAccessStatsList)) {
            return null;
        }
        // 基础访问数据
        UrlShortenerAccessLogsVo urlShortenerAccessLogsVo = urlShortenerAccessLogsRepository.findPvUvUidStatsByUrlShortener(urlShortenerStatsReq);
        // 基础访问详情
        List<UrlShortenerAccessLogsVo> dailyList = new ArrayList<>();
        List<String> rangeDates = DateUtil.rangeToList(
                        DateUtil.parse(urlShortenerStatsReq.getStartDate()),
                        DateUtil.parse(urlShortenerStatsReq.getEndDate()),
                        DateField.DAY_OF_MONTH)
                .stream()
                .map(DateUtil::formatDate)
                .toList();
        rangeDates.forEach(each -> urlShortenerAccessStatsList.stream()
                .filter(item -> Objects.equals(each, DateUtil.formatDate(item.getAccessDate())))
                .findFirst()
                .ifPresentOrElse(item -> {
                    UrlShortenerAccessLogsVo accessLogsVo = UrlShortenerAccessLogsVo.builder()
                            .date(each)
                            .pv(item.getPv())
                            .uv(item.getUv())
                            .uip(item.getUip())
                            .build();
                    dailyList.add(accessLogsVo);
                }, () -> {
                    UrlShortenerAccessLogsVo accessLogsVo = UrlShortenerAccessLogsVo.builder()
                            .date(each)
                            .pv(0)
                            .uv(0)
                            .uip(0)
                            .build();
                    dailyList.add(accessLogsVo);
                }));
        // 地区访问详情
        List<UrlShortenerStatsLocaleVo> localeCnStatsList = new ArrayList<>();
        List<UrlShortenerLocaleStats> localeListByUrlShortener = urlShortenerLocaleStatsRepository.localeListByUrlShortener(urlShortenerStatsReq);
        int localeCnSum = localeListByUrlShortener.stream()
                .mapToInt(UrlShortenerLocaleStats::getCnt)
                .sum();
        localeListByUrlShortener.forEach(each -> {
            double ratio = (double) each.getCnt() / localeCnSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsLocaleVo urlShortenerStatsLocaleVo = UrlShortenerStatsLocaleVo.builder()
                    .cnt(each.getCnt())
                    .locale(each.getProvince())
                    .ratio(actualRatio)
                    .build();
            localeCnStatsList.add(urlShortenerStatsLocaleVo);
        });
        // 小时访问详情
        List<Integer> hourStatsList = new ArrayList<>();
        List<UrlShortenerAccessStats> hourStatsByUrlShortenerList = urlShortenerAccessStatsRepository.hourStatsByUrlShortenerList(urlShortenerStatsReq);
        for (int i = 0; i < 24; i++) {
            AtomicInteger hour = new AtomicInteger(i);
            int hourCnt = hourStatsByUrlShortenerList.stream()
                    .filter(each -> Objects.equals(each.getHour(), hour.get()))
                    .findFirst()
                    .map(UrlShortenerAccessStats::getPv)
                    .orElse(0);
            hourStatsList.add(hourCnt);
        }
        // 高频访问IP详情
        List<UrlShortenerStatsTopIpVo> topIpStatsList = new ArrayList<>();
        List<HashMap<String, Object>> topIpByUrlShortenerList = urlShortenerAccessLogsRepository.topIpByUrlShortenerList(urlShortenerStatsReq);
        topIpByUrlShortenerList.forEach(each -> {
            UrlShortenerStatsTopIpVo statsTopIpVo = UrlShortenerStatsTopIpVo.builder()
                    .ip(each.get("ip").toString())
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .build();
            topIpStatsList.add(statsTopIpVo);
        });
        // 一周访问详情
        List<Integer> weekdayStatsList = new ArrayList<>();

        List<UrlShortenerAccessStats> weekdayStatsByUrlShortenerList = urlShortenerAccessStatsRepository.weekdayStatsByUrlShortenerList(urlShortenerStatsReq);
        for (int i = 1; i < 8; i++) {
            AtomicInteger weekday = new AtomicInteger(i);
            int weekdayCnt = weekdayStatsByUrlShortenerList.stream()
                    .filter(each -> Objects.equals(each.getWeekday(), weekday.get()))
                    .findFirst()
                    .map(UrlShortenerAccessStats::getPv)
                    .orElse(0);
            weekdayStatsList.add(weekdayCnt);
        }
        // 浏览器访问详情
        List<UrlShortenerStatsBrowserVo> browserStatsList = new ArrayList<>();
        List<HashMap<String, Object>> browserStatsByUrlShortenerList = urlShortenerBrowserStatsRepository.browserStatsByUrlShortenerList(urlShortenerStatsReq);
        int browserSum = browserStatsByUrlShortenerList.stream()
                .mapToInt(each -> Integer.parseInt(each.get("count").toString()))
                .sum();
        browserStatsByUrlShortenerList.forEach(each -> {
            double ratio = (double) Integer.parseInt(each.get("count").toString()) / browserSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsBrowserVo urlShortenerStatsBrowserVo = UrlShortenerStatsBrowserVo.builder()
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .browser(each.get("browser").toString())
                    .ratio(actualRatio)
                    .build();
            browserStatsList.add(urlShortenerStatsBrowserVo);
        });
        // 操作系统访问详情
        List<UrlShortenerStatsOsVo> osStatsList = new ArrayList<>();
        List<HashMap<String, Object>> osStatsByUrlShortenerList = urlShortenerOsStatsRepository.osStatsByUrlShortenerList(urlShortenerStatsReq);
        int osSum = osStatsByUrlShortenerList.stream()
                .mapToInt(each -> Integer.parseInt(each.get("count").toString()))
                .sum();
        osStatsByUrlShortenerList.forEach(each -> {
            double ratio = (double) Integer.parseInt(each.get("count").toString()) / osSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsOsVo urlShortenerStatsOsVo = UrlShortenerStatsOsVo.builder()
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .os(each.get("os").toString())
                    .ratio(actualRatio)
                    .build();
            osStatsList.add(urlShortenerStatsOsVo);
        });
        // 访客访问类型详情
        List<UrlShortenerStatsUvVo> uvTypeStatsList = new ArrayList<>();
        HashMap<String, Object> findUvTypeByUrlShortenerList = urlShortenerAccessLogsRepository.findUvTypeByUrlShortenerList(urlShortenerStatsReq);
        int oldUserCnt = Integer.parseInt(
                Optional.ofNullable(findUvTypeByUrlShortenerList)
                        .map(each -> each.get("oldUserCnt"))
                        .map(Object::toString)
                        .orElse("0")
        );
        int newUserCnt = Integer.parseInt(
                Optional.ofNullable(findUvTypeByUrlShortenerList)
                        .map(each -> each.get("newUserCnt"))
                        .map(Object::toString)
                        .orElse("0")
        );
        int uvSum = oldUserCnt + newUserCnt;
        double oldRatio = (double) oldUserCnt / uvSum;
        double actualOldRatio = Math.round(oldRatio * 100.0) / 100.0;
        double newRatio = (double) newUserCnt / uvSum;
        double actualNewRatio = Math.round(newRatio * 100.0) / 100.0;
        UrlShortenerStatsUvVo newUvVo = UrlShortenerStatsUvVo.builder()
                .uvType("newUser")
                .cnt(newUserCnt)
                .ratio(actualNewRatio)
                .build();
        uvTypeStatsList.add(newUvVo);
        UrlShortenerStatsUvVo oldUvVo = UrlShortenerStatsUvVo.builder()
                .uvType("oldUser")
                .cnt(oldUserCnt)
                .ratio(actualOldRatio)
                .build();
        uvTypeStatsList.add(oldUvVo);
        // 访问设备类型详情
        List<UrlShortenerStatsDeviceVo> deviceStatsList = new ArrayList<>();
        List<UrlShortenerDeviceStats> deviceStatsByUrlShortenerList = urlShortenerDeviceStatsRepository.deviceStatsByUrlShortenerList(urlShortenerStatsReq);
        int deviceSum = deviceStatsByUrlShortenerList.stream()
                .mapToInt(UrlShortenerDeviceStats::getCnt)
                .sum();
        deviceStatsByUrlShortenerList.forEach(each -> {
            double ratio = (double) each.getCnt() / deviceSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsDeviceVo urlShortenerStatsDeviceVo = UrlShortenerStatsDeviceVo.builder()
                    .cnt(each.getCnt())
                    .device(each.getDevice())
                    .ratio(actualRatio)
                    .build();
            deviceStatsList.add(urlShortenerStatsDeviceVo);
        });
        // 访问网络类型详情
        List<UrlShortenerStatsNetworkVo> networkStatsList = new ArrayList<>();
        List<UrlShortenerNetworkStats> networkStatsByUrlShortenerList = urlShortenerNetworkStatsRepository.networkStatsByUrlShortenerList(urlShortenerStatsReq);
        int networkSum = networkStatsByUrlShortenerList.stream()
                .mapToInt(UrlShortenerNetworkStats::getCnt)
                .sum();
        networkStatsByUrlShortenerList.forEach(each -> {
            double ratio = (double) each.getCnt() / networkSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsNetworkVo urlShortenerStatsNetworkVo = UrlShortenerStatsNetworkVo.builder()
                    .cnt(each.getCnt())
                    .network(each.getNetwork())
                    .ratio(actualRatio)
                    .build();
            networkStatsList.add(urlShortenerStatsNetworkVo);
        });
        return UrlShortenerStatsResp.builder()
                .pv(ObjectUtils.isEmpty(urlShortenerAccessLogsVo) ? 0 : urlShortenerAccessLogsVo.getPv())
                .uv(ObjectUtils.isEmpty(urlShortenerAccessLogsVo) ? 0 : urlShortenerAccessLogsVo.getUv())
                .uip(ObjectUtils.isEmpty(urlShortenerAccessLogsVo) ? 0 : urlShortenerAccessLogsVo.getUip())
                .dailyList(dailyList)
                .localeCnStatsList(localeCnStatsList)
                .hourStats(hourStatsList)
                .topIpStatsList(topIpStatsList)
                .weekdayStats(weekdayStatsList)
                .browserStatsList(browserStatsList)
                .osStatsList(osStatsList)
                .uvTypeStatsList(uvTypeStatsList)
                .deviceStatsList(deviceStatsList)
                .networkStatsList(networkStatsList)
                .build();
    }

    public Object groupUrlShortenerStats(UrlShortenerGroupStatsReq urlShortenerGroupStatsReq) {
        checkGroupBelongToUser(urlShortenerGroupStatsReq.getGid());
        List<UrlShortenerAccessStats> urlShortenerAccessStatsByGroupList = urlShortenerAccessStatsRepository.urlShortenerAccessStatsByGroupList(urlShortenerGroupStatsReq);
        if (CollUtil.isEmpty(urlShortenerAccessStatsByGroupList)) {
            return null;
        }
        // 基础访问数据
        UrlShortenerAccessLogsVo urlShortenerAccessLogsVoByGroup = urlShortenerAccessLogsRepository.findUrlShortenerAccessLogsVoByGroup(urlShortenerGroupStatsReq);
        // 基础访问详情
        List<UrlShortenerAccessLogsVo> dailyList = new ArrayList<>();
        List<String> rangeDates = DateUtil.rangeToList(
                        DateUtil.parse(urlShortenerGroupStatsReq.getStartDate()),
                        DateUtil.parse(urlShortenerGroupStatsReq.getEndDate()),
                        DateField.DAY_OF_MONTH)
                .stream()
                .map(DateUtil::formatDate)
                .toList();
        rangeDates.forEach(each -> urlShortenerAccessStatsByGroupList.stream()
                .filter(item -> Objects.equals(each, DateUtil.formatDate(item.getAccessDate())))
                .findFirst()
                .ifPresentOrElse(item -> {
                    UrlShortenerAccessLogsVo accessLogsVo = UrlShortenerAccessLogsVo.builder()
                            .date(each)
                            .pv(item.getPv())
                            .uv(item.getUv())
                            .uip(item.getUip())
                            .build();
                    dailyList.add(accessLogsVo);
                }, () -> {
                    UrlShortenerAccessLogsVo accessLogsVo = UrlShortenerAccessLogsVo.builder()
                            .date(each)
                            .pv(0)
                            .uv(0)
                            .uip(0)
                            .build();
                    dailyList.add(accessLogsVo);
                }));
        // 地区访问详情
        List<UrlShortenerStatsLocaleVo> localeCnStatsList = new ArrayList<>();
        List<UrlShortenerLocaleStats> urlShortenerLocaleStatsByGroupList = urlShortenerLocaleStatsRepository.urlShortenerLocaleStatsByGroupList(urlShortenerGroupStatsReq);
        int localeCnSum = urlShortenerLocaleStatsByGroupList.stream()
                .mapToInt(UrlShortenerLocaleStats::getCnt)
                .sum();
        urlShortenerLocaleStatsByGroupList.forEach(each -> {
            double ratio = (double) each.getCnt() / localeCnSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsLocaleVo urlShortenerStatsLocaleVo = UrlShortenerStatsLocaleVo.builder()
                    .cnt(each.getCnt())
                    .locale(each.getProvince())
                    .ratio(actualRatio)
                    .build();
            localeCnStatsList.add(urlShortenerStatsLocaleVo);
        });
        // 小时访问详情
        List<Integer> hourStatsList = new ArrayList<>();
        List<UrlShortenerAccessStats> hourStatsByGroupList = urlShortenerAccessStatsRepository.hourStatsByGroupList(urlShortenerGroupStatsReq);
        for (int i = 0; i < 24; i++) {
            AtomicInteger hour = new AtomicInteger(i);
            int hourCnt = hourStatsByGroupList.stream()
                    .filter(each -> Objects.equals(each.getHour(), hour.get()))
                    .findFirst()
                    .map(UrlShortenerAccessStats::getPv)
                    .orElse(0);
            hourStatsList.add(hourCnt);
        }
        // 高频访问IP详情
        List<UrlShortenerStatsTopIpVo> topIpStatsList = new ArrayList<>();
        List<HashMap<String, Object>> topIpByGroupList = urlShortenerAccessLogsRepository.topIpByGroupList(urlShortenerGroupStatsReq);
        topIpByGroupList.forEach(each -> {
            UrlShortenerStatsTopIpVo urlShortenerStatsTopIpVo = UrlShortenerStatsTopIpVo.builder()
                    .ip(each.get("ip").toString())
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .build();
            topIpStatsList.add(urlShortenerStatsTopIpVo);
        });
        // 一周访问详情
        List<Integer> weekdayStatsList = new ArrayList<>();
        List<UrlShortenerAccessStats> weekdayStatsByGroupList = urlShortenerAccessStatsRepository.weekdayStatsByGroupList(urlShortenerGroupStatsReq);
        for (int i = 1; i < 8; i++) {
            AtomicInteger weekday = new AtomicInteger(i);
            int weekdayCnt = weekdayStatsByGroupList.stream()
                    .filter(each -> Objects.equals(each.getWeekday(), weekday.get()))
                    .findFirst()
                    .map(UrlShortenerAccessStats::getPv)
                    .orElse(0);
            weekdayStatsList.add(weekdayCnt);
        }
        // 浏览器访问详情
        List<UrlShortenerStatsBrowserVo> browserStatsList = new ArrayList<>();
        List<HashMap<String, Object>> browserStatsByGroupList = urlShortenerBrowserStatsRepository.browserStatsByGroupList(urlShortenerGroupStatsReq);
        int browserSum = browserStatsByGroupList.stream()
                .mapToInt(each -> Integer.parseInt(each.get("count").toString()))
                .sum();
        browserStatsByGroupList.forEach(each -> {
            double ratio = (double) Integer.parseInt(each.get("count").toString()) / browserSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsBrowserVo urlShortenerStatsBrowserVo = UrlShortenerStatsBrowserVo.builder()
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .browser(each.get("browser").toString())
                    .ratio(actualRatio)
                    .build();
            browserStatsList.add(urlShortenerStatsBrowserVo);
        });
        // 操作系统访问详情
        List<UrlShortenerStatsOsVo> osStatsList = new ArrayList<>();
        List<HashMap<String, Object>> osStatsByGroupList = urlShortenerOsStatsRepository.osStatsByGroupList(urlShortenerGroupStatsReq);
        int osSum = osStatsByGroupList.stream()
                .mapToInt(each -> Integer.parseInt(each.get("count").toString()))
                .sum();
        osStatsByGroupList.forEach(each -> {
            double ratio = (double) Integer.parseInt(each.get("count").toString()) / osSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsOsVo urlShortenerStatsOsVo = UrlShortenerStatsOsVo.builder()
                    .cnt(Integer.parseInt(each.get("count").toString()))
                    .os(each.get("os").toString())
                    .ratio(actualRatio)
                    .build();
            osStatsList.add(urlShortenerStatsOsVo);
        });
        // 访问设备类型详情
        List<UrlShortenerStatsDeviceVo> deviceStatsList = new ArrayList<>();
        List<UrlShortenerDeviceStats> deviceStatsByGroupList = urlShortenerDeviceStatsRepository.deviceStatsByGroupList(urlShortenerGroupStatsReq);
        int deviceSum = deviceStatsByGroupList.stream()
                .mapToInt(UrlShortenerDeviceStats::getCnt)
                .sum();
        deviceStatsByGroupList.forEach(each -> {
            double ratio = (double) each.getCnt() / deviceSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsDeviceVo urlShortenerStatsDeviceVo = UrlShortenerStatsDeviceVo.builder()
                    .cnt(each.getCnt())
                    .device(each.getDevice())
                    .ratio(actualRatio)
                    .build();
            deviceStatsList.add(urlShortenerStatsDeviceVo);
        });
        // 访问网络类型详情
        List<UrlShortenerStatsNetworkVo> networkStatsList = new ArrayList<>();
        List<UrlShortenerNetworkStats> networkStatsByGroupList = urlShortenerNetworkStatsRepository.networkStatsByGroupList(urlShortenerGroupStatsReq);
        int networkSum = networkStatsByGroupList.stream()
                .mapToInt(UrlShortenerNetworkStats::getCnt)
                .sum();
        networkStatsByGroupList.forEach(each -> {
            double ratio = (double) each.getCnt() / networkSum;
            double actualRatio = Math.round(ratio * 100.0) / 100.0;
            UrlShortenerStatsNetworkVo urlShortenerStatsNetworkVo = UrlShortenerStatsNetworkVo.builder()
                    .cnt(each.getCnt())
                    .network(each.getNetwork())
                    .ratio(actualRatio)
                    .build();
            networkStatsList.add(urlShortenerStatsNetworkVo);
        });

        return UrlShortenerStatsResp.builder()
                .pv(urlShortenerAccessLogsVoByGroup.getPv())
                .uv(urlShortenerAccessLogsVoByGroup.getUv())
                .uip(urlShortenerAccessLogsVoByGroup.getUip())
                .dailyList(dailyList)
                .localeCnStatsList(localeCnStatsList)
                .hourStats(hourStatsList)
                .topIpStatsList(topIpStatsList)
                .weekdayStats(weekdayStatsList)
                .browserStatsList(browserStatsList)
                .osStatsList(osStatsList)
                //.uvTypeStatsList(uvTypeStatsList)
                .deviceStatsList(deviceStatsList)
                .networkStatsList(networkStatsList)
                .build();

    }

    public PageInfo<UrlShortenerStatsAccessRecordVo> urlShortenerStatsAccessRecord(UrlShortenerStatsAccessRecordReq req) {
        checkGroupBelongToUser(req.getGid());
        PageInfo<UrlShortenerAccessLogs> urlShortenerAccessLogsPageInfo = urlShortenerAccessLogsRepository.selectStatsAccessRecordPage(req);

        if (CollUtil.isEmpty(urlShortenerAccessLogsPageInfo.getList())) {
            return new PageInfo<UrlShortenerStatsAccessRecordVo>();
        }
        PageInfo<UrlShortenerStatsAccessRecordVo> urlShortenerStatsAccessRecordVoPageInfo = UrlShortenerAccessLogsMapstruct.INSTANCE.urlShortenerAccessLogsListToUrlShortenerStatsAccessRecordVoList(urlShortenerAccessLogsPageInfo);

        List<String> userAccessLogsList = urlShortenerStatsAccessRecordVoPageInfo.getList().stream()
                .map(UrlShortenerStatsAccessRecordVo::getUser)
                .toList();
        List<Map<String, Object>> uvTypeList = urlShortenerAccessLogsRepository.selectUvTypeByUsers(
                req.getGid(),
                req.getFullShortUrl(),
                req.getEnableStatus(),
                req.getStartDate(),
                req.getEndDate(),
                userAccessLogsList
        );
        urlShortenerStatsAccessRecordVoPageInfo.getList().forEach(each -> {
            String uvType = uvTypeList.stream()
                    .filter(item -> Objects.equals(each.getUser(), item.get("user")))
                    .findFirst()
                    .map(item -> item.get("uvType"))
                    .map(Object::toString)
                    .orElse("旧访客");
            each.setUvType(uvType);
        });
        return urlShortenerStatsAccessRecordVoPageInfo;
    }

    public PageInfo<UrlShortenerStatsAccessRecordVo> groupUrlShortenerStatsAccessRecord(UrlShortenerGroupStatsAccessRecordReq req) {
        checkGroupBelongToUser(req.getGid());
        PageInfo<UrlShortenerAccessLogs> urlShortenerAccessLogsPageInfo = urlShortenerAccessLogsRepository.selectAccessLogsGroupPage(req);
        if (CollUtil.isEmpty(urlShortenerAccessLogsPageInfo.getList())) {
            return new PageInfo<UrlShortenerStatsAccessRecordVo>();
        }

        PageInfo<UrlShortenerStatsAccessRecordVo> urlShortenerStatsAccessRecordVoPageInfo = UrlShortenerAccessLogsMapstruct.INSTANCE.urlShortenerAccessLogsListToUrlShortenerStatsAccessRecordVoList(urlShortenerAccessLogsPageInfo);

        List<String> userAccessLogsList = urlShortenerStatsAccessRecordVoPageInfo.getList().stream()
                .map(UrlShortenerStatsAccessRecordVo::getUser)
                .toList();
        List<Map<String, Object>> uvTypeList = urlShortenerAccessLogsRepository.selectGroupUvTypeByUsers(
                req.getGid(),
                req.getStartDate(),
                req.getEndDate(),
                userAccessLogsList
        );
        urlShortenerStatsAccessRecordVoPageInfo.getList().forEach(each -> {
            String uvType = uvTypeList.stream()
                    .filter(item -> Objects.equals(each.getUser(), item.get("user")))
                    .findFirst()
                    .map(item -> item.get("uvType"))
                    .map(Object::toString)
                    .orElse("旧访客");
            each.setUvType(uvType);
        });
        return urlShortenerStatsAccessRecordVoPageInfo;
    }


    public void checkGroupBelongToUser(String gid) throws ServerException {

        Optional.ofNullable(SecurityContextHolder.getUserName())
                .orElseThrow(() -> new ServerException("用户未登录"));

    }


}
